package com.kunpan.admin.exception;

import cn.dev33.satoken.exception.*;
import com.kunpan.admin.common.domain.AjaxResult;
import com.kunpan.admin.constant.HttpStatus;
import com.kunpan.admin.exception.file.InsufficientSpaceException;
import com.kunpan.admin.exception.file.MinIOFileStorageException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

/**
 * 全局异常拦截器
 */
@ControllerAdvice //此注解表示为此类被定义为全局异常处理类
public class MyExceptionHandle {

    private final Logger log = LoggerFactory.getLogger(MyExceptionHandle.class);

    // 定义一些常量，避免硬编码
    private static final String TOKEN_EXPIRED = "token 已过期";
    private static final String TOKEN_INVALID = "token 无效";
    private static final String TOKEN_FROZEN = "token 已被冻结";
    private static final String TOKEN_LOGGED_OUT = "token 已被顶下线";

    /**
     * 全局异常处理
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public AjaxResult handleException(Exception e) {
        String msg;
        int code;
        // 捕获SQL错误
        if (e instanceof BadSqlGrammarException) {
            code = HttpStatus.ERROR;
            msg = "数据库语法错误，请联系管理员";
        } else {
            code = HttpStatus.ERROR;
            msg = e.getMessage();
        }

        // 记录日志并返回
        log.error("全局异常处理：", e);
        return AjaxResult.error(code, msg);
    }

    /**
     * 处理运行时异常以及SaToken异常
     */
    @ResponseBody
    @ExceptionHandler(RuntimeException.class)
    public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        String msg = "";
        int code = HttpStatus.ERROR;

        // 判断不同的异常类型，优化了多个 if-else 判断
        if (e instanceof NotLoginException) {
            NotLoginException ee = (NotLoginException) e;
            String message = ee.getMessage();
            if (message.contains(TOKEN_EXPIRED) || message.contains(TOKEN_FROZEN)) {
                code = HttpStatus.IDENTITY_EXPIRED;
//                code = HttpStatus.UNAUTHORIZED;
                msg = "重试";
            } else if (message.contains(TOKEN_INVALID)) {
                code = HttpStatus.UNAUTHORIZED;
                msg = "登入已过期,请重新登入";
            } else if (message.contains(TOKEN_LOGGED_OUT)) {
                code = HttpStatus.CONFLICT;
                msg = "您的账号在别处登入";
            } else {
                code = HttpStatus.FORBIDDEN;
                msg = "未登入,无法访问系统资源";
            }
        } else if (e instanceof NotRoleException) {
            NotRoleException ee = (NotRoleException) e;
            code = HttpStatus.FORBIDDEN;
            msg = "不是：" + ee.getRole() + " 无权操作";
        } else if (e instanceof NotPermissionException) {
            NotPermissionException ee = (NotPermissionException) e;
            code = HttpStatus.FORBIDDEN;
            msg = "无此权限：" + ee.getCode();
        } else if (e instanceof DisableServiceException) {
            DisableServiceException ee = (DisableServiceException) e;
            code = HttpStatus.ACCOUNT_BANNED;
            msg = "账号被封禁：" + ee.getDisableTime() + "秒后解封";
        } else if (e instanceof InsufficientSpaceException) {
            InsufficientSpaceException ee = (InsufficientSpaceException) e;
            code = HttpStatus.WARN;
            msg = ee.getMessage();
        }
        // 记录日志并返回
        log.error("请求地址: {}, 异常信息: {}", request.getRequestURI(), e);
        return AjaxResult.error(code, msg);
    }

    @ResponseBody
    @ExceptionHandler(MinIOFileStorageException.class)
    public AjaxResult handleFileStorageException(MinIOFileStorageException e) {
        log.error("文件服务异常: {}", e.getMessage()); // 已记录详细日志，此处可简化
        return AjaxResult.error("文件服务暂不可用");
    }
}